// STUNProtocol.cpp: implementation of the CTurnMessage class.
//
//////////////////////////////////////////////////////////////////////

#include "mysocket.h"
#include "TurnMessage.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "osplatform.h"
#include <assert.h>
#ifdef USE_DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

void ShowCommand(int command)
{
	switch(command)
	{
	case 0X0001:		
		printf("STUN_COMMAND_BIND_REQUEST\r\n");
		break;
	case 0X0002:
		printf("STUN_COMMAND_SHARED_SECRET_REQUEST\r\n");
		break;
	case 0X0003:
		printf("TURN_COMMAND_ALLOCATE_REQUEST\r\n");
		break;
	case 0X0004:
		printf("TURN_COMMAND_SEND_REQUEST\r\n");
		break;
	case 0X0010: 
		printf("TURN_COMMAND_ALLOCATE_CHANNEL_REQUEST\r\n");
		break;
	case 0X0011: 
		printf("TURN_COMMAND_RELEASE_CHANNEL_REQUEST\r\n");
		break;
	case 0X0012:
		printf("TURN_COMMAND_START_RECORD_REQUEST\r\n");
		break;
	case 0X0013: 
		printf("TURN_COMMAND_STOP_RECORD_REQUEST\r\n");
		break;
	case 0X0101: 
		printf("STUN_COMMAND_BIND_RESPONSE\r\n");
		break;
	case 0X0111: 
		printf("STUN_COMMAND_BIND_ERROR_RESPONSE\r\n");
		break;
	case 0X0102:
		printf("STUN_COMMAND_SHARED_SECRET_RESPONSE\r\n");
		break;
	case 0X0112:
		printf("STUN_COMMAND_SHARED_SECRET_ERROR_RESPONSE\r\n");
		break;
	//TURN draft rosenberg-midcom-turn-07
	case 0X0103: 
		printf("TURN_COMMAND_ALLOCATE_RESPONSE\r\n");
		break;
	case 0X0113: 
		printf("TURN_COMMAND_ALLOCATE_ERROR_RESPONSE\r\n");
		break;
	case 0X0104: 
		printf("TURN_COMMAND_SEND_RESPONSE\r\n");
		break;
	case 0X0114:
		printf("TURN_COMMAND_SEND_ERROR_RESPONSE\r\n");
		break;
	case 0X0115: 
		printf("TURN_COMMAND_DATA_INDICATION\r\n");
		break;
	case 0X0200: 
		printf("TURN_COMMAND_ALLOCATE_CHANNEL_RESPONSE\r\n");
		break;
	case 0X0201:
		printf("TURN_COMMAND_ALLOCATE_CHANNEL_ERROR_RESPONSE\r\n");
		break;
	case 0X0202:
		printf("TURN_COMMAND_RELEASE_CHANNEL_RESPONSE\r\n");
		break;
	case 0X0203:
		printf("TURN_COMMAND_RELEASE_CHANNEL_ERROR_RESPONSE\r\n");
		break;
	case 0X0204: 
		printf("TURN_COMMAND_START_RECORD_RESPONSE\r\n");
		break;
	case 0X0205:
		printf("TURN_COMMAND_START_RECORD_ERROR_RESPONSE\r\n");
		break;
	case 0X0206:
		printf("TURN_COMMAND_STOP_RECORD_RESPONSE\r\n");
		break;
	case 0X0207:
		printf("TURN_COMMAND_STOP_RECORD_ERROR_RESPONSE\r\n");
		break;
	}
}
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CTurnMessage::CTurnMessage()
{
	m_nCommand = 0;
	m_nLength = 0;
	memset(m_TransactionID,0,16);
	m_pMappedAddress = NULL;
    m_pResponseAddress = NULL;
    m_pChangeRequest = NULL;
    m_pSourceAddress = NULL;
    m_pChangedAddress = NULL;
    m_pUserName = NULL;
    m_pPassword = NULL;
    m_pMessageIntegrity = NULL;
    m_pErrorCode = NULL;
    m_pUnknownAttributes = NULL;
    m_pReflectedFrom = NULL;
	m_pNonce = NULL;
	m_pLifeTime = NULL;
	m_pStartTime = NULL;
	m_pStopTime = NULL;
	m_pMagicCookie = NULL;
	m_pAlternateServer = NULL;
	m_pBandwidth = NULL;
	m_pRealm = NULL;
	m_pDestinationAddress = NULL;
	m_pDATA = NULL;
	m_pData = NULL;
	m_nDataLength = 0;
	m_pChannelID = NULL;
	m_pRecordID = NULL;
	m_pOwnerID = NULL;
	m_pVideoFormat = NULL;
	m_pVideoFrameRate = NULL;
	m_pVideoHeight = NULL;
	m_pVideoWidth = NULL;
	m_pSubTitle = NULL;
	m_pSubTitlePos = NULL;
	m_pTimeTitlePos = NULL;
	m_pRecvChannel = NULL;
	m_pRelayChannel = NULL;
	m_pRelayServerID = NULL;
	// added by liuhf 2007.10.10
	m_pPlayScale = NULL;
	m_pPlayType = NULL;
}

CTurnMessage::~CTurnMessage()
{
	Clear();
}

bool CTurnMessage::Parse(const char *pdata, int len)
{
	Clear();
	unsigned char *p = (unsigned char *)pdata;
	int n = 0;
	m_nCommand = ntohs(*(unsigned short *)p);


	p+=2;
	n+=2;
	m_nLength = ntohs(*(unsigned short *)p);
	p+=2;
	n+=2;
	memcpy(m_TransactionID, p, 16);
	p+=16;
	n+=16;
	if(m_nLength + 20 > len)
		return false;
	m_pData = new char[m_nLength + 20];
	memcpy(m_pData, pdata, 20);
	m_nDataLength = 20;
	n = m_nLength;
	int attritype;
	int attrilen;
	int length;
	while(n > 0)
	{
		attritype = ntohs(*(unsigned short *)p);
		p+=2;
		n-=2;
		attrilen = ntohs(*(unsigned short *)p);
		p+=2;
		n-=2;
		if(attrilen > n)
			return false;
		p-=4;
		n+=4;
		switch(attritype)
		{		
		case MS_ATTRIBUTE_RECV_CHANNEL:
			{
				if(m_pRecvChannel)
				{
					delete m_pRecvChannel;
				}
				m_pRecvChannel = new CRecvChannel;
				length = m_pRecvChannel->Decode(p,n);
				if(length == -1)
					return false;
				memcpy(&m_pData[m_nDataLength],p,length);
				m_nDataLength += length;

				p+=length;
				n-=length;
			}
			break;
		case MS_ATTRIBUTE_RELAY_CHANNEL:
			{
				if(m_pRelayChannel)
				{
					delete m_pRelayChannel;
				}
				m_pRelayChannel = new CRelayChannel;
				length = m_pRelayChannel->Decode(p,n);
				if(length == -1)
					return false;
				memcpy(&m_pData[m_nDataLength],p,length);
				m_nDataLength += length;

				p+=length;
				n-=length;
			}
			break;	
		case MS_ATTRIBUTE_RELAY_SERVER_ID:
			{
			
				if(m_pRelayServerID)
				{
					delete m_pRelayServerID;
				}
				m_pRelayServerID = new CRelayServerID;
				length = m_pRelayServerID->Decode(p,n);
				if(length == -1)
					return false;
				memcpy(&m_pData[m_nDataLength],p,length);
				m_nDataLength += length;

				p+=length;
				n-=length;
			}
			break;
		case STUN_ATTRIBUTE_MAPPED_ADDRESS:
			{
				if(m_pMappedAddress)
				{
					delete m_pMappedAddress;
				}
				m_pMappedAddress = new CMappedAddress;
				length = m_pMappedAddress->Decode(p,n);
				if(length == -1)
					return false;
				memcpy(&m_pData[m_nDataLength],p,length);
				m_nDataLength += length;

				p+=length;
				n-=length;
			}
			break;
		case STUN_ATTRIBUTE_RESPONSE_ADDRESS:
			{
				if(m_pResponseAddress)
					delete m_pResponseAddress;
				m_pResponseAddress = new CResponseAddress;
				length = m_pResponseAddress->Decode(p,n);
				if(length == -1)
					return false;
				memcpy(&m_pData[m_nDataLength],p,length);
				m_nDataLength += length;
				p+=length;
				n-=length;
			}
			break;
		case STUN_ATTRIBUTE_CHANGE_REQUEST:
			{
				if(m_pChangeRequest)
					delete m_pChangeRequest;
				m_pChangeRequest = new CChangeRequest;
				length = m_pChangeRequest->Decode(p,n);
				if(length == -1)
					return false;
				memcpy(&m_pData[m_nDataLength],p,length);
				m_nDataLength += length;
				p +=length;
				n -=length;
			}
			break;
		case STUN_ATTRIBUTE_SOURCE_ADDRESS:
			{
				if(m_pSourceAddress)
					delete m_pSourceAddress;
				m_pSourceAddress = new CSourceAddress;
				length = m_pSourceAddress->Decode(p,n);
				if(length == -1)
					return false;
				memcpy(&m_pData[m_nDataLength],p,length);
				m_nDataLength += length;
				p+=length;
				n-=length;
			}
			break;
		case STUN_ATTRIBUTE_CHANGED_ADDRESS:
			{
				if(m_pChangedAddress)
					delete m_pChangedAddress;
				m_pChangedAddress = new CChangedAddress;
				length = m_pChangedAddress->Decode(p,n);
				if(length == -1)
					return false;
				memcpy(&m_pData[m_nDataLength],p,length);
				m_nDataLength += length;
				p+=length;
				n-=length;
			}
			break;
		case STUN_ATTRIBUTE_USERNAME:
			{
				if(m_pUserName)
					delete m_pUserName;
				m_pUserName = new CUserName;
				length = m_pUserName->Decode(p,n);
				if(length == -1)
					return false;
				memcpy(&m_pData[m_nDataLength],p,length);
				m_nDataLength += length;
				p+=length;
				n-=length;
			}
			break;
		case STUN_ATTRIBUTE_PASSWORD:
			{
				if(m_pPassword)
					delete m_pPassword;
				m_pPassword = new CPassword;
				length = m_pPassword->Decode(p,n);
				if(length == -1)
					return false;
				memcpy(&m_pData[m_nDataLength],p,length);
				m_nDataLength += length;
				p+=length;
				n-=length;
			}
			break;
		case TURN_ATTRIBUTE_CHANNEL_ID:
			{
				if(m_pChannelID)
					delete m_pChannelID;
				m_pChannelID = new CChannelID;
				length = m_pChannelID->Decode(p,n);
				if(length == -1)
					return false;
				memcpy(&m_pData[m_nDataLength],p,length);
				m_nDataLength += length;
				p+=length;
				n-=length;
			}
			break;		
		case STUN_ATTRIBUTE_MESSAGE_INTEGRITY:
			{
				if(m_pMessageIntegrity)
				{
					delete m_pMessageIntegrity;
				}
				m_pMessageIntegrity = new CMessageIntegrity;
				length = m_pMessageIntegrity->Decode(p,n);
				if(length == -1)
					return false;
				p+=length;
				n-=length;
			}
			break;
		case STUN_ATTRIBUTE_ERROR_CODE:
			{
				if(m_pErrorCode)
					delete m_pErrorCode;
				m_pErrorCode = new CErrorCode;
				length = m_pErrorCode->Decode(p,n);
				if(length == -1)
					return false;
				memcpy(&m_pData[m_nDataLength],p,length);
				m_nDataLength += length;
				p+=length;
				n-=length;
			}
			break;
		case STUN_ATTRIBUTE_UNKNOWN_ATTRIBUTES:
			{
				if(m_pUnknownAttributes)
					delete m_pUnknownAttributes;
				m_pUnknownAttributes = new CUnknownAttributes;
				length = m_pUnknownAttributes->Decode(p,n);
				if(length == -1)
					return false;
				memcpy(&m_pData[m_nDataLength],p,length);
				m_nDataLength += length;
				p+=length;
				n-=length;
			}
			break;
		case STUN_ATTRIBUTE_REFLECTED_FROM:
			{
				if(m_pReflectedFrom)
					delete m_pReflectedFrom;
				m_pReflectedFrom = new CReflectedFrom;
				length = m_pReflectedFrom->Decode(p,n);
				if(length == -1)
					return false;
				memcpy(&m_pData[m_nDataLength],p,length);
				m_nDataLength += length;
				p+=length;
				n-=length;
			}
			break;
		case TURN_ATTRIBUTE_NONCE:
			{
				if(m_pNonce)
					delete m_pNonce;
				m_pNonce = new CNonce;
				length = m_pNonce->Decode(p,n);
				if(length == -1)
					return false;
				memcpy(&m_pData[m_nDataLength],p,length);
				m_nDataLength += length;
				p+=length;
				n-=length;
			}
			break;
		case TURN_ATTRIBUTE_REALM:
			{
				if(m_pRealm)
					delete m_pRealm;
				m_pRealm = new CRealm;
				length = m_pRealm->Decode(p,n);
				if(length == -1)
					return false;
				memcpy(&m_pData[m_nDataLength],p,length);
				m_nDataLength += length;
				p+=length;
				n-=length;
			}
			break;
		case TURN_ATTRIBUTE_BANDWIDTH:
			{
				if(m_pBandwidth)
					delete m_pBandwidth;
				m_pBandwidth = new CBandwidth;
				length = m_pBandwidth->Decode(p,n);
				if(length == -1)
					return false;
				memcpy(&m_pData[m_nDataLength],p,length);
				m_nDataLength += length;
				p+=length;
				n-=length;
			}
			break;
		case TURN_ATTRIBUTE_LIFETIME:
			{
				if(m_pLifeTime)
					delete m_pLifeTime;
				m_pLifeTime = new CLifeTime;
				length = m_pLifeTime->Decode(p,n);
				if(length == -1)
					return false;
				memcpy(&m_pData[m_nDataLength],p,length);
				m_nDataLength += length;
				p+=length;
				n-=length;
			}
			break;
		case TURN_ATTRIBUTE_START_TIME:
			{
				if(m_pStartTime)
					delete m_pStartTime;
				m_pStartTime = new CStartTime;
				length = m_pStartTime->Decode(p,n);
				if(length == -1)
					return false;
				memcpy(&m_pData[m_nDataLength],p,length);
				m_nDataLength += length;
				p+=length;
				n-=length;
			}
			break;
		case TURN_ATTRIBUTE_STOP_TIME:
			{
				if(m_pStopTime)
					delete m_pStopTime;
				m_pStopTime = new CStopTime;
				length = m_pStopTime->Decode(p,n);
				if(length == -1)
					return false;
				memcpy(&m_pData[m_nDataLength],p,length);
				m_nDataLength += length;
				p+=length;
				n-=length;
			}
			break;
		case TURN_ATTRIBUTE_VIDEO_WIDTH:
			{
				if(m_pVideoWidth)
					delete m_pVideoWidth;
				m_pVideoWidth = new CVideowidth;
				length = m_pVideoWidth->Decode(p,n);
				if(length == -1)
					return false;
				memcpy(&m_pData[m_nDataLength],p,length);
				m_nDataLength += length;
				p+=length;
				n-=length;
			}
			break;//0x0017
		case TURN_ATTRIBUTE_VIDEO_HEIGHT:
			{
				if(m_pVideoHeight)
					delete m_pVideoHeight;
				m_pVideoHeight = new CVideoheight;
				length = m_pVideoHeight->Decode(p,n);
				if(length == -1)
					return false;
				memcpy(&m_pData[m_nDataLength],p,length);
				m_nDataLength += length;
				p+=length;
				n-=length;
			}
			break;//0x0018
		case TURN_ATTRIBUTE_VIDEO_FORMAT:
			{
				if(m_pVideoFormat)
					delete m_pVideoFormat;
				m_pVideoFormat = new CVideoformat;
				length = m_pVideoFormat->Decode(p,n);
				if(length == -1)
					return false;
				memcpy(&m_pData[m_nDataLength],p,length);
				m_nDataLength += length;
				p+=length;
				n-=length;
			}
			break;//0x0019
		case TURN_ATTRIBUTE_VIDEO_FRAMERATE:
			{
				if(m_pVideoFrameRate)
					delete m_pVideoFrameRate;
				m_pVideoFrameRate = new CVideoframerate;
				length = m_pVideoFrameRate->Decode(p,n);
				if(length == -1)
					return false;
				memcpy(&m_pData[m_nDataLength],p,length);
				m_nDataLength += length;
				p+=length;
				n-=length;
			}
			break;//0x001a
		case TURN_ATTRIBUTE_RECORD_ID:
			{
				if(m_pRecordID)
					delete m_pRecordID;
				m_pRecordID = new CRecordID;
				length = m_pRecordID->Decode(p,n);
				if(length == -1)
					return false;
				memcpy(&m_pData[m_nDataLength],p,length);
				m_nDataLength += length;
				p+=length;
				n-=length;
			}
			break;//0x001b
		case TURN_ATTRIBUTE_OWNER_ID:
			{
				if(m_pOwnerID)
					delete m_pOwnerID;
				m_pOwnerID = new COwnerID;
				length = m_pOwnerID->Decode(p,n);
				if(length == -1)
					return false;
				memcpy(&m_pData[m_nDataLength],p,length);
				m_nDataLength += length;
				p+=length;
				n-=length;
			}
			break;//0x001b
		case TURN_ATTRIBUTE_SUBTITLE_POS:
			{
				if(m_pSubTitlePos)
					delete m_pSubTitlePos;
				m_pSubTitlePos = new CSubTitlePos;
				length = m_pSubTitlePos->Decode(p,n);
				if(length == -1)
					return false;
				memcpy(&m_pData[m_nDataLength],p,length);
				m_nDataLength += length;
				p+=length;
				n-=length;
			}
			break;
		case TURN_ATTRIBUTE_TIMETITLE_POS:
			{
				if(m_pTimeTitlePos)
					delete m_pTimeTitlePos;
				m_pTimeTitlePos = new CTimeTitlePos;
				length = m_pTimeTitlePos->Decode(p,n);
				if(length == -1)
					return false;
				memcpy(&m_pData[m_nDataLength],p,length);
				m_nDataLength += length;
				p+=length;
				n-=length;
			}
			break;
		case TURN_ATTRIBUTE_SUBTITLE:
			{
				if(m_pSubTitle)
					delete m_pSubTitle;
				m_pSubTitle = new CSubTitle;
				length = m_pSubTitle->Decode(p,n);
				if(length == -1)
					return false;
				memcpy(&m_pData[m_nDataLength],p,length);
				m_nDataLength += length;
				p+=length;
				n-=length;
			}
			break;
		case TURN_ATTRIBUTE_DATA:
			{
				if(m_pDATA)
					delete m_pDATA;
				m_pDATA = new CData;
				length = m_pDATA->Decode(p,n);
				if(length == -1)
					return false;
				//memcpy(&m_pData[m_nDataLength],p,length);
				//m_nDataLength += length;
				p+=length;
				n-=length;
			}
			break;
		case TURN_ATTRIBUTE_MAGIC_COOKIE:
			{
				memcpy(&m_pData[m_nDataLength],p,attrilen+4);
				m_nDataLength += attrilen+4;
				p+=(attrilen+4);
				n-=(attrilen+4);
				assert(m_nDataLength <= m_nLength+20);
			}
			break;
			
		// added by liuhf 2007.10.10
		case TURN_ATTRIBUTE_PLAY_SCALE:
			{
				if(m_pPlayScale)
					delete m_pPlayScale;
				m_pPlayScale = new CPlayScale;
				length = m_pPlayScale->Decode(p,n);
				if(length == -1)
					return false;
				memcpy(&m_pData[m_nDataLength],p,length);
				m_nDataLength += length;
				p+=length;
				n-=length;
			}
			break;

		case TURN_ATTRIBUTE_PLAY_TYPE:
			{
				if(m_pPlayType)
					delete m_pPlayType;
				m_pPlayType = new CPlayType;
				length = m_pPlayType->Decode(p,n);
				if(length == -1)
					return false;
				memcpy(&m_pData[m_nDataLength],p,length);
				m_nDataLength += length;
				p+=length;
				n-=length;
			}
			break;
			
		// added by liuhf 2007.10.10

		default:
			{//
				//printf("error type\n");
				memcpy(&m_pData[m_nDataLength],p,attrilen+4);
				m_nDataLength += attrilen+4;
				assert(m_nDataLength <= m_nLength+20);
				if(m_nDataLength <= m_nLength+20)
					return false;
				p+=(attrilen+4);
				n-=(attrilen+4);
			}
			break;
		}
		assert(m_nDataLength <= m_nLength+20);
	}	
#ifdef SHOW_DEBUG
	ShowCommand(m_nCommand);
#endif
	return true;
}


void CTurnMessage::Clear()
{
	if(m_pMappedAddress)
	{
		delete m_pMappedAddress;
		m_pMappedAddress = NULL;
	}
	if(m_pResponseAddress)
	{
		delete m_pResponseAddress;
		m_pResponseAddress = NULL;
	}
    if(m_pChangeRequest)
	{
		delete m_pChangeRequest;
		m_pChangeRequest = NULL;
	}
	if(m_pSourceAddress)
	{
		delete m_pSourceAddress;
		m_pSourceAddress = NULL;
	}
	if(m_pChangedAddress)
	{
		delete m_pChangedAddress;
		m_pChangedAddress = NULL;
	}
	if(m_pUserName)
	{
		delete m_pUserName;
		m_pUserName = NULL;
	}
	if(m_pPassword)
	{
		delete m_pPassword;
		m_pPassword = NULL;
	}
	if(m_pChannelID)
	{
		delete m_pChannelID;
		m_pChannelID = NULL;
	}
	if(m_pMessageIntegrity)
	{
		delete m_pMessageIntegrity;
		m_pMessageIntegrity = NULL;
	}
	if(m_pErrorCode)
	{
		delete m_pErrorCode;
		m_pErrorCode = NULL;
	}
	if(m_pUnknownAttributes)
	{
		delete m_pUnknownAttributes;
		m_pUnknownAttributes = NULL;
	}
	if(m_pReflectedFrom)
	{
		delete m_pReflectedFrom;
		m_pReflectedFrom = NULL;
	}
	if(m_pNonce)
	{
		delete m_pNonce;
		m_pNonce = NULL;
	}
	if(m_pRealm)
	{
		delete m_pRealm;
		m_pRealm = NULL;
	}
	if(m_pLifeTime)
	{
		delete m_pLifeTime;
		m_pLifeTime = NULL;
	}
	if(m_pStartTime)
	{
		delete m_pStartTime;
		m_pStartTime = NULL;
	}
	if(m_pStopTime)
	{
		delete m_pStopTime;
		m_pStopTime = NULL;
	}
	if(m_pMagicCookie)
	{
		delete m_pMagicCookie;
		m_pMagicCookie = NULL;
	}
	if(m_pAlternateServer)
	{
		delete m_pAlternateServer;
		m_pAlternateServer = NULL;
	}
	if(m_pBandwidth)
	{
		delete m_pBandwidth;
		m_pBandwidth = NULL;
	}
	if(m_pDestinationAddress)
	{
		delete m_pDestinationAddress;
		m_pDestinationAddress = NULL;
	}
	if(m_pDATA)
	{
		delete m_pDATA;
		m_pDATA = NULL;
	}
	if(m_pData)
	{
		delete[] m_pData;
		m_pData = NULL;
	}	
	if(m_pRecordID)
	{
		delete m_pRecordID;
		m_pRecordID = NULL;
	}
	if(m_pOwnerID)
	{
		delete m_pOwnerID;
		m_pOwnerID = NULL;
	}
	if(m_pVideoFormat)
	{
		delete m_pVideoFormat;
		m_pVideoFormat = NULL;
	}
	if(m_pVideoFrameRate)
	{
		delete m_pVideoFrameRate;
		m_pVideoFrameRate = NULL;
	}
	if(m_pVideoHeight)
	{
		delete m_pVideoHeight;
		m_pVideoHeight = NULL;
	}
	if(m_pVideoWidth)
	{
		delete m_pVideoWidth;
		m_pVideoWidth = NULL;
	}
	if(m_pRecvChannel)
	{
		delete m_pRecvChannel;
		m_pRecvChannel = NULL;
	}
	if(m_pRelayChannel)
	{
		delete m_pRelayChannel;
		m_pRelayChannel = NULL;
	}
	if(m_pRelayServerID)
	{
		delete m_pRelayServerID;
		m_pRelayServerID = NULL;
	}

	// added by liuhf 2007.10.10
	if(m_pPlayScale)
	{
		delete m_pPlayScale;
		m_pPlayScale = NULL;
	}
	if(m_pPlayType)
	{
		delete m_pPlayType;
		m_pPlayType = NULL;
	}
	// added by liuhf 2007.10.10

	m_nDataLength = 0;

}
void CTurnMessage::AddMappedAddress(CMappedAddress *pmap)
{
	if(m_pMappedAddress)
	{
		delete m_pMappedAddress;
		
	}
	m_pMappedAddress = pmap;
}
void CTurnMessage::AddResponseAddress(CResponseAddress *pr)
{
	if(m_pResponseAddress)
	{
		delete m_pResponseAddress;
		
	}
	m_pResponseAddress = pr;
}
void CTurnMessage::AddChangeRequest(CChangeRequest *pc)
{
    if(m_pChangeRequest)
	{
		delete m_pChangeRequest;
		
	}
	m_pChangeRequest = pc;
}
void CTurnMessage::AddSourceAddress(CSourceAddress *ps)
{
	if(m_pSourceAddress)
	{
		delete m_pSourceAddress;
		
	}
	m_pSourceAddress = ps;
}
void CTurnMessage::AddChangedAddress(CChangedAddress *pc)
{
	if(m_pChangedAddress)
	{
		delete m_pChangedAddress;
		
	}
	m_pChangedAddress = pc;
}
void CTurnMessage::AddUserName(CUserName *pu)
{
	if(m_pUserName)
	{
		delete m_pUserName;		
	}
	m_pUserName = pu;
}
void CTurnMessage::AddPassword(CPassword *pp)
{
	if(m_pPassword)
	{
		delete m_pPassword;
		
	}
	m_pPassword = pp;
}

void CTurnMessage::AddChannelID(CChannelID *pp)
{
	if(m_pChannelID)
	{
		delete m_pChannelID;		
	}
	m_pChannelID = pp;
}

void CTurnMessage::AddMessageIntegrity(CMessageIntegrity *pm)
{
	if(m_pMessageIntegrity)
	{
		delete m_pMessageIntegrity;
		
	}
	m_pMessageIntegrity = pm;
}
void CTurnMessage::AddErrorCode(CErrorCode *pec)
{
	if(m_pErrorCode)
	{
		delete m_pErrorCode;
		
	}
	m_pErrorCode = pec;
}
void CTurnMessage::AddUnknownAttributes(CUnknownAttributes *pu)
{
	if(m_pUnknownAttributes)
	{
		delete m_pUnknownAttributes;
	}
	m_pUnknownAttributes = pu;
}
void CTurnMessage::AddReflectedFrom(CReflectedFrom *pr)
{
	if(m_pReflectedFrom)
	{
		delete m_pReflectedFrom;
		
	}
	m_pReflectedFrom = pr;
}
void CTurnMessage::AddNonce(CNonce *pnonce)
{
	if(m_pNonce)
		delete m_pNonce;
	m_pNonce = pnonce;
}
void CTurnMessage::AddRealm(CRealm *prm)
{
	if(m_pRealm)
		delete m_pRealm;
	m_pRealm = prm;
}
void CTurnMessage::AddLifeTime(CLifeTime *plt)
{
	if(m_pLifeTime)
		delete m_pLifeTime;
	m_pLifeTime = plt;
}
void CTurnMessage::AddStartTime(CStartTime *pst)
{
	if(m_pStartTime)
		delete m_pStartTime;
	m_pStartTime = pst;
}
void CTurnMessage::AddStopTime(CStopTime *pet)
{
	if(m_pStopTime)
		delete m_pStopTime;
	m_pStopTime = pet;
}
void CTurnMessage::AddMagicCookie(CMagicCookie *pmc)
{
	if(m_pMagicCookie)
		delete m_pMagicCookie;
	m_pMagicCookie = pmc;
}
void CTurnMessage::AddAlternateServer(CAlternateServer*	pas)
{
	if(m_pAlternateServer)
		delete m_pAlternateServer;
	m_pAlternateServer = pas;
}
void CTurnMessage::AddBandwidth(CBandwidth* pbw)
{
	if(m_pBandwidth)
		delete m_pBandwidth;
	m_pBandwidth = pbw;
}
void CTurnMessage::AddDestinationAddress(CDestinationAddress*	pda)
{
	if(m_pDestinationAddress)
		delete m_pDestinationAddress;
	m_pDestinationAddress = pda;

}
void CTurnMessage::AddData(CData *pdata)
{
	if(m_pDATA)
		delete m_pDATA;
	m_pDATA = pdata;
}

void CTurnMessage::AddRecordID(CRecordID*	pRecordID)
{
	if(m_pRecordID)
		delete m_pRecordID;
	m_pRecordID = pRecordID;
}

void CTurnMessage::AddOwnerID(COwnerID*	pOwnerID)
{
	if(m_pOwnerID)
		delete m_pOwnerID;
	m_pOwnerID = pOwnerID;
}

void CTurnMessage::AddVideoFormat(CVideoformat*	pVideoFormat)
{
	if(m_pVideoFormat)
		delete m_pVideoFormat;
	m_pVideoFormat = pVideoFormat;
}

void CTurnMessage::AddVideoFrameRate(CVideoframerate*	pVideoFrameRate)
{
	if(m_pVideoFrameRate)
		delete m_pVideoFrameRate;
	m_pVideoFrameRate = pVideoFrameRate;
}

void CTurnMessage::AddVideoHeight(CVideoheight*	pVideoHeight)
{
	if(m_pVideoHeight)
		delete m_pVideoHeight;
	m_pVideoHeight = pVideoHeight;
}

void CTurnMessage::AddVideoWidth(CVideowidth*	pVideoWidth)
{
	if(m_pVideoWidth)
		delete m_pVideoWidth;
	m_pVideoWidth = pVideoWidth;
}


void CTurnMessage::AddSubTitle(CSubTitle *pSubTitle)
{
	if(m_pSubTitle)
		delete m_pSubTitle;
	m_pSubTitle = pSubTitle;
}

void CTurnMessage::AddSubTitlePos(CSubTitlePos *pSubTitlePos)
{
	if(m_pSubTitlePos)
		delete m_pSubTitlePos;
	m_pSubTitlePos = pSubTitlePos;
}

void CTurnMessage::AddTimeTitlePos(CTimeTitlePos *pTimeTitlePos)
{
	if(m_pTimeTitlePos)
		delete m_pTimeTitlePos;
	m_pTimeTitlePos = pTimeTitlePos;
}

void CTurnMessage::AddRecvChannel(CRecvChannel *pchid)
{
	if(m_pRecvChannel)
		delete m_pRecvChannel;
	m_pRecvChannel = pchid;
}
void CTurnMessage::AddRelayChannel(CRelayChannel *prid)
{
	if(m_pRelayChannel)
		delete m_pRelayChannel;
	m_pRelayChannel = prid;
}
void CTurnMessage::AddRelayServerID(CRelayServerID *psid)
{
	if(m_pRelayServerID)
		delete m_pRelayServerID;
	m_pRelayServerID = psid;
}

// added by liuhf 2007.10.10
void CTurnMessage::AddPlayScale(CPlayScale* pScale)
{
	if(m_pPlayScale)
		delete m_pPlayScale;
	m_pPlayScale = pScale;
}

void CTurnMessage::AddPlayType(CPlayType* pType)
{
	if(m_pPlayType)
		delete m_pPlayType;
	m_pPlayType = pType;
}
// added by liuhf 2007.10.10

int CTurnMessage::Encode(char *pdata,int len)
{
	int n = 0;
	int m;
#ifdef SHOW_DEBUG
	ShowCommand(m_nCommand);
#endif
	unsigned char *p = (unsigned char *)pdata;
	unsigned short *plen;
	*(unsigned short *)p = htons(m_nCommand);
	p+=2;
	plen = (unsigned short *)p;
	p+=2;
	memcpy(p,m_TransactionID,16);
	p+=16;
	*(unsigned short *)p = htons(TURN_ATTRIBUTE_MAGIC_COOKIE);
	p+=2;
	n+=2;
	*(unsigned short *)p = htons(4);
	p+=2;
	n+=2;
	unsigned long magic = htonl(0x72c64bc6);
	memcpy(p,&magic, 4);
	p+=4;
	n+=4;

	if(m_pMappedAddress)
	{
		m = m_pMappedAddress->Encode(p,len-n);
		if(m == -1)
			return -1;
		n+=m;
		p+=m;
	}
    if(m_pResponseAddress)
	{
		m = m_pResponseAddress->Encode(p,len-n);
		if(m == -1)
			return -1;
		n+=m;
		p+=m;
	}
    if(m_pChangeRequest)
	{
		m = m_pChangeRequest->Encode(p,len-n);
		if(m == -1)
			return -1;
		n+=m;
		p+=m;
	}
    if(m_pSourceAddress)
	{
		m = m_pSourceAddress->Encode(p,len-n);
		if(m == -1)
			return -1;
		n+=m;
		p+=m;
	}
    if(m_pChangedAddress)
	{
		m = m_pChangedAddress->Encode(p,len-n);
		n+=m;
		p+=m;
	}
    if(m_pUserName)
	{
		m = m_pUserName->Encode(p,len-n);
		if(m == -1)
			return -1;
		n+=m;
		p+=m;
	}
    if(m_pPassword)
	{
		m = m_pPassword->Encode(p,len-n);
		if(m == -1)
			return -1;
		n+=m;
		p+=m;
	}
	
    if(m_pChannelID)
	{
		m = m_pChannelID->Encode(p,len-n);
		if(m == -1)
			return -1;
		n+=m;
		p+=m;
	}
	
    if(m_pErrorCode)
	{
		m = m_pErrorCode->Encode(p,len-n);
		if(m == -1)
			return -1;
		n+=m;
		p+=m;
	}
    if(m_pUnknownAttributes)
	{
		m = m_pUnknownAttributes->Encode(p,len-n);
		if(m == -1)
			return -1;
		n+=m;
		p+=m;
	}
	if(m_pLifeTime)
	{
		m = m_pLifeTime->Encode(p,len-n);
		if(m == -1)
			return -1;
		n+=m;
		p+=m;
	}
	if(m_pStartTime)
	{
		m = m_pStartTime->Encode(p,len-n);
		if(m == -1)
			return -1;
		n+=m;
		p+=m;
	}
	if(m_pStopTime)
	{
		m = m_pStopTime->Encode(p,len-n);
		if(m == -1)
			return -1;
		n+=m;
		p+=m;
	}
    if(m_pReflectedFrom)
	{
		m = m_pReflectedFrom->Encode(p,len-n);
		if(m == -1)
			return -1;
		n+=m;
		p+=m;
	}
	if(m_pRealm)
	{
		m = m_pRealm->Encode(p,len-n);
		if(m == -1)
			return -1;
		n+=m;
		p+=m;
	}
	if(m_pNonce)
	{
		m = m_pNonce->Encode(p,len-n);
		if(m == -1)
			return -1;
		n+=m;
		p+=m;
	}
	if(m_pRecvChannel)
	{
		m = m_pRecvChannel->Encode(p,len-n);
		if(m == -1)
			return -1;
		n+=m;
		p+=m;
	}
	if(m_pRelayChannel)
	{
		m = m_pRelayChannel->Encode(p,len-n);
		if(m == -1)
			return -1;
		n+=m;
		p+=m;
	}
	if(m_pRelayServerID)
	{
		m = m_pRelayServerID->Encode(p,len-n);
		if(m == -1)
			return -1;
		n+=m;
		p+=m;
	}
	if(m_pDATA)
	{
		m = m_pDATA->Encode(p,len-n);
		if(m == -1)
			return -1;
		n+=m;
		p+=m;
	}
	if(m_pRecordID)
	{
		m = m_pRecordID->Encode(p,len-n);
		if(m == -1)
			return -1;
		n+=m;
		p+=m;
	}
	if(m_pOwnerID)
	{
		m = m_pOwnerID->Encode(p,len-n);
		if(m == -1)
			return -1;
		n+=m;
		p+=m;
	}
	if(m_pVideoFormat)
	{
		m = m_pVideoFormat->Encode(p,len-n);
		if(m == -1)
			return -1;
		n+=m;
		p+=m;
	}
	if(m_pVideoFrameRate)
	{
		m = m_pVideoFrameRate->Encode(p,len-n);
		if(m == -1)
			return -1;
		n+=m;
		p+=m;
	}
	if(m_pVideoHeight)
	{
		m = m_pVideoHeight->Encode(p,len-n);
		if(m == -1)
			return -1;
		n+=m;
		p+=m;
	}
	if(m_pVideoWidth)
	{
		m = m_pVideoWidth->Encode(p,len-n);
		if(m == -1)
			return -1;
		n+=m;
		p+=m;
	}
	if(m_pSubTitlePos)
	{
		m = m_pSubTitlePos->Encode(p,len-n);
		if(m == -1)
			return -1;
		n+=m;
		p+=m;
	}
	if(m_pTimeTitlePos)
	{
		m = m_pTimeTitlePos->Encode(p,len-n);
		if(m == -1)
			return -1;
		n+=m;
		p+=m;
	}
	if(m_pSubTitle)
	{
		m = m_pSubTitle->Encode(p,len-n);
		if(m == -1)
			return -1;
		n+=m;
		p+=m;
	}
	if(m_pMessageIntegrity)
	{
		m = m_pMessageIntegrity->Encode(p,len-n);
		if(m ==-1)
			return -1;
		n+=m;
		p+=m;
	}

	// added by liuhf 2007.10.10
	if(m_pPlayScale)
	{
		m = m_pPlayScale->Encode(p,len-n);
		if(m ==-1)
			return -1;
		n+=m;
		p+=m;
	}
	
	if(m_pPlayType)
	{
		m = m_pPlayType->Encode(p,len-n);
		if(m ==-1)
			return -1;
		n+=m;
		p+=m;
	}
	// added by liuhf 2007.10.10

	*plen = htons(n);
	return n+20;
}


void CTurnMessage::GeneralID(char *pid)
{
	timeval tv;
	unsigned long c;
	for(int i=0;i<16;i+=4)
	{
		gettimeofday(&tv,0);
		c = tv.tv_sec*1000 + tv.tv_usec/1000;
		pid[i+0] = (char)(c&0xff);
		pid[i+1] = (char)((c>>8)&0xff);
		pid[i+2] = (char)((c>>16)&0xff);
		pid[i+3] = (char)((c>>24)&0xff);
	//	usleep(2000);
	}
}


